package club.kingyin.kyblogprofile.service;

import club.kingyin.commons.entity.file.File;
import club.kingyin.commons.enums.BlogEnum;
import club.kingyin.commons.response.Result;
import club.kingyin.kyblogprofile.dao.FileDao;
import club.kingyin.kyblogprofile.entity.Folder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URLDecoder;
import java.time.ZonedDateTime;
import java.util.*;

@Service
public class BucketService {

    @Autowired
    private MinioClient minioClient;

    @Resource
    private FileDao fileDao;

    @Value("${cloud.domain}")
    private String domain;


    public Result contains(String bucketName) {
        try {
            boolean res = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            return Result.success(res);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    public Result buckets() {
        try {
            List<String> buckets = new ArrayList<String>();
            for (Bucket bucket : minioClient.listBuckets()) {
                buckets.add(bucket.name());
            }
            return Result.success(buckets);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public Folder filesByBucketName(String bucketName, String prefix) {
        Folder folder = new Folder();
        Iterable<io.minio.Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(false).build());
        long currentTimeMillis = System.currentTimeMillis();
        for (io.minio.Result<Item> object : results) {
            try {
                Item item = object.get();
                folder.add(URLDecoder.decode(item.objectName(),"utf-8"), item.size(), !item.isDir()?item.lastModified():null, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("耗时"+(System.currentTimeMillis()-currentTimeMillis));
        return folder;
    }
    public Folder foldersByBucketName(String bucketName, String prefix, boolean world) {
        Map<String, BlogEnum> files = null;
        Folder folder = new Folder();
        // 是否是当前路径
        boolean current = false;
        String path = prefix.substring(1);
        if (!world) {
            // 获取共享列表
            LambdaQueryWrapper<File> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.likeRight(File::getPath, path).select(File::getPath, File::getStatus);
            files = new HashMap<>();
            for (File file : fileDao.selectList(queryWrapper)) {
                if (!current) {
                    if (file.getPath().equals(path))
                        current = true;
                }
                files.put(file.getPath(),file.getStatus());
            }
            // 该路径没有共享文件
            if(files.isEmpty()) {
                return folder;
            }
        }

        for (io.minio.Result<Item> object : minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(false).build())) {
            try {
                Item item = object.get();
                if (item.isDir() && world) {
                    folder.add(URLDecoder.decode(item.objectName(),"utf-8"), item.size(), null, true);
                } else if(!world) {
                    String name = URLDecoder.decode(item.objectName(), "utf-8");
                    // 是当前目录
                    if (current) {
                        if (files.get(name) == null || files.get(name) == BlogEnum.SHARE)
                            folder.add(name, item.size(), !item.isDir()?item.lastModified():null, false);
                    } else {
                        // 不在当前目录
                        if(files.get(name) != null && files.get(name) == BlogEnum.SHARE)
                            folder.add(name, item.size(), !item.isDir()?item.lastModified():null, false);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return folder;
    }


    public void mkdir(String bucketName, String prefix) {
        try {
            minioClient.putObject(
                    PutObjectArgs.builder().bucket(bucketName).object(prefix).stream(
                            new ByteArrayInputStream(new byte[] {}), 0, -1)
                            .build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void remove(String bucketName, String prefix) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(prefix).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String uploadFileInputStream(String bucketName,String name, InputStream inputStream, String contentType, boolean timestamp) {
        name = timestamp?getFileName(name):name;
        try {
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(name)
                    .stream(inputStream, inputStream.available(), -1)
                    .contentType(contentType).build());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return domain+name;
    }

    private String getFileName(String objectName) {
        //判断文件最后一个点所在的位置
        int lastIndexOf = objectName.lastIndexOf(".");
        if (lastIndexOf == -1) {
            return String.format("%s_%s", objectName, System.currentTimeMillis());
        } else {
            // 获取文件前缀,已最后一个点进行分割
            String filePrefix = objectName.substring(0, objectName.lastIndexOf("."));
            // 获取文件后缀,已最后一个点进行分割
            String fileSuffix = objectName.substring(objectName.lastIndexOf(".") + 1);
            // 组成唯一文件名
            return String.format("%s_%s.%s", filePrefix, System.currentTimeMillis(), fileSuffix);
        }
    }
}
